using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;

namespace GameDriver
{
    /// <summary>
    /// A class representing the collection of scenes that make up a game.
    /// </summary>
    public class SceneManager
    {
        public Game Game;
        private Stack<Scene> scenes;

        /// <summary>
        /// Create a new scene manager.
        /// </summary>
        /// <param name="g">A reference to the Game class.</param>
        public SceneManager(Game g)
        {
            Game = g;
            scenes = new Stack<Scene>();
        }

        #region Public Methods
        /// <summary>
        /// Add a scene to the manager and make it active.
        /// </summary>
        /// <param name="s">The new scene.</param>
        /// <param name="unpause">If true the scene is unpaused after it is added - defaults to false.</param>
        public void PushScene(Scene s, bool unpause = false)
        {
            if (scenes.Count > 0)
                scenes.Peek().Pause();

            scenes.Push(s);
            if (unpause)
                s.Unpause();
        }
        /// <summary>
        /// Remove the currently active scene from the manager.
        /// </summary>
        /// <param name="pause">If true the scene is pased after removal - defaults to false.</param>
        /// <returns>The scene which was removed.</returns>
        public Scene PopScene(bool pause = false)
        {
            Scene s = scenes.Pop();
            if (pause)
                s.Pause();
            else
                s.Content.Unload();

            if (scenes.Count > 0)
                scenes.Peek().Unpause();

            return s;
        }

        /// <summary>
        /// Update the currently active scene - should be called once per frame.
        /// </summary>
        /// <param name="gt">The current running/passed time for the game.</param>
        public void Update(GameTime gt)
        {
            if (Game.IsActive)
                if (scenes.Count > 0)
                    scenes.Peek().Update(gt);
        }
        /// <summary>
        /// Draw the currently active scene to the screen - should be called once per frame.
        /// </summary>
        /// <param name="sb">The SpriteBatch to use for rendering.</param>
        public void Draw(SpriteBatch sb)
        {
            if (scenes.Count > 0)
                scenes.Peek().Draw(sb);
        }

        /// <summary>
        /// Exit the game cleanly.
        /// </summary>
        public void Exit()
        {
            Game.Exit();
        }
        #endregion
    }
}
